import { ref, onMounted, onBeforeUnmount } from 'vue'

// 如你所见，核心逻辑完全一致，我们做的只是把它移到一个外部函数中去，并返回需要暴露的状态。
// 和在组件中一样，你也可以在组合式函数中使用所有的组合式 API。
// 现在，useMouse() 的功能可以在任何组件中轻易复用了。

// 每一个调用 useMouse() 的组件实例会创建其独有的 x、y 状态拷贝，因此他们不会互相影响。如果你想要在组件之间共享状态，请使用pinia

// 组合式函数约定用驼峰命名法命名，并以“use”作为开头。
export function useMouse() {
  // 被组合式函数封装和管理的状态
  const x = ref(0)
  const y = ref(0)

  // 组合式函数可以随时更改其状态
  const updateXY = (event: MouseEvent) => {
    x.value = event.pageX
    y.value = event.pageY
  }

  // 一个组合式函数也可以挂靠在所属组件的生命周期上
  // 来启动和卸载副作用
  onMounted(() => {
    window.addEventListener('mousemove', updateXY)
  })
  onBeforeUnmount(() => {
    window.removeEventListener('mousemove', updateXY)
  })

  // 通过返回值暴露所管理的状态
  return { x, y }
}

// 返回值
// 你可能已经注意到了，我们一直在组合式函数中使用 ref() 而不是 reactive()。
// 我们推荐的约定是组合式函数始终返回一个包含多个 ref 的普通的非响应式对象，这样该对象在组件中被解构为 ref 之后仍可以保持响应性

// x 和 y 是两个 ref
// const { x, y } = useMouse()
